package cn.jinjimi.app.managers;

import android.graphics.Bitmap;
import android.net.Uri;
import android.view.View;

import com.facebook.common.executors.CallerThreadExecutor;
import com.facebook.common.references.CloseableReference;
import com.facebook.datasource.BaseDataSubscriber;
import com.facebook.datasource.DataSource;
import com.facebook.datasource.DataSubscriber;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.imagepipeline.image.CloseableBitmap;
import com.facebook.imagepipeline.image.CloseableImage;
import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.imagepipeline.request.ImageRequestBuilder;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import cn.jinjimi.base.Task.TaskExecutor;
import cn.jinjimi.base.util.GsonUtils;
import cn.jinjimi.framework.helper.annotation.EventTrace;
import cn.jinjimi.framework.helper.annotation.EventTraceSelector;
import cn.jinjimi.framework.helper.annotation.EventTraceWhenTrue;
import cn.jinjimi.app.AccountManager;
import cn.jinjimi.app.AppContext;
import cn.jinjimi.app.bean.EventDataField;
import cn.jinjimi.app.bean.EventID;
import cn.jinjimi.app.controller.event.AnonymousEvent;
import cn.jinjimi.app.controller.event.DataEvent;
import cn.jinjimi.app.controller.event.FinishRegisterEvent;
import cn.jinjimi.app.controller.event.LoginSuccessEvent;
import cn.jinjimi.app.entity.GuideAlertData;
import cn.jinjimi.app.managers.task.BaseTask;
import cn.jinjimi.app.managers.task.GuideTask;
import cn.jinjimi.app.managers.task.IPoolChangeObserver;
import cn.jinjimi.app.managers.task.TaskPoolManager;
import cn.jinjimi.app.managers.task.TaskPoolName;
import cn.jinjimi.framework.router.Router;
import cn.jinjimi.app.store.DatabaseManager;
import cn.jinjimi.app.main.activity.LoginActivity;
import cn.jinjimi.app.main.widget.HomeGuideView;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.EventBusException;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.json.JSONArray;
import org.json.JSONException;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

;

/**
 * Created by lforxeverc on 2016/10/24.
 */

public class GuideManager {
    public static final String GUIDE_CACHE_KEY = "guide_cache_key";
    //下拉view
    private HomeGuideView mView;
    //是否正在显示
    private boolean isShowing = false;
    //接受事件
    private EventHandler handler = new EventHandler();
    //缓存所有alert信息
    private Map<String, GuideAlertData> mAlertMaps = new HashMap<>();
    //缓存session alert的id信息
    private List<String> sessionAlertIds = new ArrayList<>();
    //当前显示的alert信息
    private GuideAlertData mCurrentData;
    private boolean isOnRightTab = false;
    static GuideManager instance = new GuideManager();

    public static GuideManager getInstance() {
        return instance;
    }

    private GuideManager() {
    }

    //程序退出前调用
    public void onTerminal() {
        unRegister();
        isShowing = false;
        sessionAlertIds.clear();
        TaskPoolManager.getInstance().cancelAllWithPoolName(TaskPoolName.GUIDE_POOL_NAME);
        mView = null;
    }

    //设置当前的引导view
    public void setGuideViews(final HomeGuideView view) {
        register();
        mView = view;
        mView.setListener(new HomeGuideView.OnGuideViewClickListener() {
            @Override
            public void onClickGuideView() {
                clickGuideView(mCurrentData.target.equals(TARGET_NEW));
            }

            @EventTrace(value = {EventID.APP_LOGIN_UPS, EventID.APP_WELCOME_LOGIN}, paramsK = {EventDataField.ParamId}, paramsV = {"2"})
            private void clickGuideView(@EventTraceSelector boolean targetNew) {
                LoginActivity.setLoginFrom(EventID.APP_WELCOME_LOGIN);
                Router.create(mView.getContext() == null ? AppContext.getInstance() : mView.getContext(), mCurrentData.content.linkUrl).open();
                hideGuideView();
            }

            @Override
            public void onClickClose() {
                closeGuidView(mCurrentData.target.equals(TARGET_NEW));
            }

            @EventTrace(value = {EventID.APP_LOGIN_UPS, EventID.APP_WELCOME_CLOSE}, paramsK = {EventDataField.ParamId}, paramsV = {"1"})
            private void closeGuidView(@EventTraceSelector boolean typeNew) {
                hideGuideView();
            }
        });
    }

    public void setViewVisibility(boolean show) {
        isOnRightTab = show;
        if (mView != null) {
            if (isShowing)
                mView.setVisibility(show ? View.VISIBLE : View.GONE);
            if (isOnRightTab) {
                TaskPoolManager.getInstance().pop(TaskPoolName.GUIDE_POOL_NAME);
            }
        }
    }

    private void showGuideView(final GuideAlertData data) {
        if (mView == null) return;
        mCurrentData = data;
        downloadImageAndShow(mCurrentData.content.imageUrl);
    }

    private void updateState() {
        mCurrentData.hasShown = true;
        if (mCurrentData.display.equals(DISPLAY_EVERYSESSION) && !sessionAlertIds.contains(mCurrentData.id)) {
            sessionAlertIds.add(mCurrentData.id);
        }
        mAlertMaps.put(mCurrentData.id, mCurrentData);
        saveCache();
    }

    private void hideGuideView() {
        if (mView == null || !isShowing) return;
        isShowing = false;
        mView.hide();
    }


    private class EventHandler {
        //target为user时接收事件
        @Subscribe(threadMode = ThreadMode.MAIN)
        public void onLoginSuccessEvent(LoginSuccessEvent event) {
            if (AccountManager.getInstance().isLogin() && event.id != LoginSuccessEvent.REGISTER) {
                TaskPoolManager.getInstance().cancelAllWithPoolName(TaskPoolName.GUIDE_POOL_NAME);
                TaskPoolManager.getInstance()
                        .push(new GuideTask() {
                                  @Override
                                  public void run() {
                                      showGuideViewWithTargetIfExist(TARGET_USER);
                                  }
                              }
                        );

            }
        }

        //target为new时接收事件
        @Subscribe(threadMode = ThreadMode.MAIN)
        public void onFinishRegisterEvent(FinishRegisterEvent event) {
            if (event.state == DataEvent.SUCC) {
                TaskPoolManager.getInstance().cancelAllWithPoolName(TaskPoolName.GUIDE_POOL_NAME);
                TaskPoolManager.getInstance()
                        .push(new GuideTask() {
                                  @Override
                                  public void run() {
                                      showGuideViewWithTargetIfExist(TARGET_NEW);
                                  }
                              }
                        );

            }
        }

        //target为anonymous时接收事件
        @Subscribe(threadMode = ThreadMode.MAIN)
        public void onAnonymousEvent(AnonymousEvent event) {
            TaskPoolManager.getInstance().cancelAllWithPoolName(TaskPoolName.GUIDE_POOL_NAME);
            TaskPoolManager.getInstance()
                    .push(new GuideTask() {
                              @Override
                              public void run() {
                                  showGuideViewWithTargetIfExist(TARGET_ANONYMOUS);
                              }
                          }
                    );

        }
    }

    //从配置信息获取数据
    public void setConfig(String data) {
        try {
            JSONArray json = new JSONArray(data);
            Map<String, GuideAlertData> cacheData = getCache();
            if (json != null && json.length() > 0) {
                mAlertMaps.clear();
                for (int i = 0; i < json.length(); i++) {
                    String object = json.getString(i);
                    GuideAlertData item = GsonUtils.fromJson(object, GuideAlertData.class);
                    String id = item.id;
                    if (cacheData != null && cacheData.containsKey(id)) {
                        mAlertMaps.put(id, cacheData.get(id));
                    } else {
                        mAlertMaps.put(id, item);
                    }
                }
                saveCache();
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

    }

    //根据是否有对应的target显示alert
    private void showGuideViewWithTargetIfExist(String target) {
        hideGuideView();
        GuideAlertData data = getDataWithTarget(target);
        if (data != null) {
            showGuideView(data);
        }
    }

    private GuideAlertData getDataWithTarget(String target) {
        for (GuideAlertData data : mAlertMaps.values()) {
            if (data.target.equals(target)) {
                if (data.display.equals(DISPLAY_ONCE) && data.hasShown) {
                    continue;
                }
                if (data.display.equals(DISPLAY_EVERYSESSION)) {
                    if (sessionAlertIds.contains(data.id)) {
                        continue;
                    }
                }
                return data;
            }
        }
        return null;
    }

    //下载图片后显示
    private void downloadImageAndShow(String url) {
        final ImageRequest imageRequest = ImageRequestBuilder.newBuilderWithSource(Uri.parse(url)).build();
        DataSource<CloseableReference<CloseableImage>> dataSource = Fresco.getImagePipeline().fetchDecodedImage(imageRequest, mView.getContext());
        DataSubscriber dataSubscriber = new BaseDataSubscriber<CloseableReference<CloseableImage>>() {
            @Override
            protected void onNewResultImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
                CloseableReference<CloseableImage> imageReference = dataSource.getResult();
                if (imageReference != null) {
                    try {
                        CloseableBitmap image = (CloseableBitmap) imageReference.get();
                        final Bitmap loadedImage = image.getUnderlyingBitmap();
                        TaskExecutor.runTaskOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                if (mView != null && loadedImage != null && imageRequest.getSourceUri().toString().equals(mCurrentData.content.imageUrl)) {
                                    isShowing = true;
                                    mView.setVisibility(View.VISIBLE);
                                    mView.setImageViewBitmap(loadedImage);
                                    mView.show();
                                    analyseShow(mCurrentData.target.equals(TARGET_ANONYMOUS));

                                    updateState();
                                }
                            }


                            @EventTrace(EventID.APP_WELCOME_SHOW)
                            private void analyseShow(@EventTraceWhenTrue boolean show) {
                            }
                        });
                    } finally {
                        dataSource.close();
                        CloseableReference.closeSafely(imageReference);
                    }
                }
            }

            @Override
            protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
            }
        };
        dataSource.subscribe(dataSubscriber, CallerThreadExecutor.getInstance());
    }

    private void saveCache() {
        DatabaseManager.getInstance().getCacheDao().saveCacheData(mAlertMaps, GUIDE_CACHE_KEY, false);
    }

    private Map<String, GuideAlertData> getCache() {
        String data = DatabaseManager.getInstance().getCacheDao().getCacheData(GUIDE_CACHE_KEY, false);
        Gson gson = new Gson();
        Type type = new TypeToken<Map<String, GuideAlertData>>() {
        }.getType();
        return gson.fromJson(data, type);
    }

    private void register() {

        if (EventBus.getDefault().isRegistered(handler))
            return;

        try {
            EventBus.getDefault().register(handler);
        } catch (EventBusException e) {

        }

        TaskPoolManager.getInstance().addTaskPoolListenerWithName(TaskPoolName.GUIDE_POOL_NAME, new IPoolChangeObserver() {
            @Override
            public void onChange(BaseTask task, boolean pushOrPop) {
                if (task != null && task.poolName().equals(TaskPoolName.GUIDE_POOL_NAME) && pushOrPop && isOnRightTab) {
                    TaskPoolManager.getInstance().pop(task.poolName());
                }
            }
        });
    }

    private void unRegister() {
        EventBus.getDefault().unregister(handler);
        TaskPoolManager.getInstance().removeAllTaskPoolListenerWithName(TaskPoolName.GUIDE_POOL_NAME);
    }


    private static final String TARGET_ANONYMOUS = "anonymous";
    private static final String TARGET_NEW = "new";
    private static final String TARGET_USER = "user";

    private static final String DISPLAY_ONCE = "once";
    private static final String DISPLAY_EVERYTIME = "everytime";
    private static final String DISPLAY_EVERYSESSION = "everysession";

}
